﻿using Microsoft.Xna.Framework;
using Black.Surface2DEngine.Graphic2D.Render2D.Process2D;

namespace Black.Surface2DEngine.Graphic2D.Render2D.Extensions
{
    /// <summary>
    /// Classe statique pour les extensions sur Entity2D
    /// </summary>
    public static class Entity2DExtensions
    {
        /// <summary>
        /// Lance un effet Arc sur l'objet
        /// </summary>
        /// <param name="p_oEntity">Objet sur qui on fait le process</param>
        /// <param name="p_fAmplitude">Amplitude entre le centre de l'arc et la base en pixel</param>
        /// <param name="p_fTranslate">Translation a faire entre les deux points (départ et arrivé) de l'arc</param>
        /// <param name="p_bOnY">TRUE arc sur l'axe X (déplacement sur Y), FALSE l'inverse</param>
        /// <param name="p_fTime">Temps pour effectuer la translation en milliseconde</param>
        /// <param name="p_bLoop">TRUE redémare le process à la fin, FALSE sinon</param>
        /// <param name="p_bInvertAtLoop">TRUE si l'on inverse le type de l'effet, FALSE sinon</param>
        /// <param name="p_iLoopOccurs">Indique combien de fois il doit boucler, NULL si boucle infinie</param>
        /// <returns>Instance du process</returns>
        public static Process2DArc Arc(this Entity2D p_oEntity, float p_fAmplitude, float p_fTranslate, bool p_bOnY, float p_fTime, bool p_bLoop, bool p_bInvertAtLoop, int? p_iLoopOccurs)
        {
            // Vérification

            if ( p_oEntity == null )
                return (null);

            // Création du process

            Process2DArc oProcess = new Process2DArc(p_oEntity, p_fAmplitude, p_fTranslate, p_bOnY, p_fTime, p_bLoop, p_bInvertAtLoop, p_iLoopOccurs);

            // Ajout au moteur

            p_oEntity.Screen.Process2DStart(oProcess);

            // On retourne le process

            return (oProcess);
        }

        /// <summary>
        /// Lance un effet Blink sur l'objet
        /// </summary>
        /// <param name="p_oEntity">Objet sur qui on fait le process</param>
        /// <param name="p_fSpeed">Interval de temps en miliseconde pour un changement d'état</param>
        /// <param name="p_fTime">Temps pour effectuer la translation en milliseconde</param>
        /// <param name="p_Loop">TRUE redémare le process à la fin, FALSE sinon</param>
        /// <param name="p_iLoopOccurs">Indique combien de fois il doit boucler, NULL si boucle infinie</param>
        /// <returns>Instance du process</returns>
        public static Process2DBlink Blink(this Entity2D p_oEntity, float p_fSpeed, float p_fTime, bool p_bLoop, int? p_iLoopOccurs)
        {
            // Vérification

            if ( p_oEntity == null )
                return (null);

            // Création du process

            Process2DBlink oProcess = new Process2DBlink(p_oEntity, p_fSpeed, p_fTime, p_bLoop, p_iLoopOccurs);

            // Ajout au moteur

            p_oEntity.Screen.Process2DStart(oProcess);

            // On retourne le process

            return (oProcess);
        }

        /// <summary>
        /// Lance un effet Fade sur l'objet
        /// </summary>
        /// <param name="p_oEntity">Objet sur qui on fait le process</param>
        /// <param name="p_fScale">Modification alpha (modification par rapport au point de départ)</param>
        /// <param name="p_fTime">Temps pour effectuer la translation en milliseconde</param>
        /// <param name="p_bLoop">TRUE redémare le process à la fin, FALSE sinon</param>
        /// <param name="p_bInvertAtLoop">TRUE si l'on inverse le type de l'effet, FALSE sinon</param>
        /// <param name="p_iLoopOccurs">Indique combien de fois il doit boucler, NULL si boucle infinie</param>
        /// <returns>Instance du process</returns>
        public static Process2DFade Fade(this Entity2D p_oEntity, int p_iAlpha, float p_fTime, bool p_bLoop, bool p_bInvertAtLoop, int? p_iLoopOccurs)
        {
            // Vérification

            if ( p_oEntity == null )
                return (null);

            // Création du process

            Process2DFade oProcess = new Process2DFade(p_oEntity, p_iAlpha, p_fTime, p_bLoop, p_bInvertAtLoop, p_iLoopOccurs);

            // Ajout au moteur

            p_oEntity.Screen.Process2DStart(oProcess);

            // On retourne le process

            return (oProcess);
        }

        /// <summary>
        /// Lance un effet Rotate sur l'objet
        /// </summary>
        /// <param name="p_oEntity">Objet sur qui on fait le process</param>
        /// <param name="p_fAngle">Angle de déplacement par rapport à celui de départ</param>
        /// <param name="p_fTime">Temps pour effectuer la rotation en milliseconde</param>
        /// <param name="p_bLoop">TRUE redémare le process à la fin, FALSE sinon</param>
        /// <param name="p_bInvertAtLoop">TRUE si l'on inverse le type de l'effet, FALSE sinon</param>
        /// <param name="p_iLoopOccurs">Indique combien de fois il doit boucler, NULL si boucle infinie</param>
        /// <returns>Instance du process</returns>
        public static Process2DRotate Rotate(this Entity2D p_oEntity, float p_fAngle, int p_fTime, bool p_bLoop, bool p_bInvertAtLoop, int? p_iLoopOccurs)
        {
            // Vérification

            if ( p_oEntity == null )
                return (null);

            // Création du process

            Process2DRotate oProcess = new Process2DRotate(p_oEntity, p_fAngle, p_fTime, p_bLoop, p_bInvertAtLoop, p_iLoopOccurs);

            // Ajout au moteur

            p_oEntity.Screen.Process2DStart(oProcess);

            // On retourne le process

            return (oProcess);
        }

        /// <summary>
        /// Lance un effet Scale sur l'objet
        /// </summary>
        /// <param name="p_oEntity">Objet sur qui on fait le process</param>
        /// <param name="p_fScale">Modification scale (modification par rapport au point de départ)</param>
        /// <param name="p_fTime">Temps pour effectuer la translation en milliseconde</param>
        /// <param name="p_bLoop">TRUE redémare le process à la fin, FALSE sinon</param>
        /// <param name="p_bInvertAtLoop">TRUE si l'on inverse le type de l'effet, FALSE sinon</param>
        /// <param name="p_iLoopOccurs">Indique combien de fois il doit boucler, NULL si boucle infinie</param>
        /// <returns>Instance du process</returns>
        public static Process2DScale Scale(this Entity2D p_oEntity, float p_fScale, float p_fTime, bool p_bLoop, bool p_bInvertAtLoop, int? p_iLoopOccurs)
        {
            // Vérification

            if ( p_oEntity == null )
                return (null);

            // Création du process

            Process2DScale oProcess = new Process2DScale(p_oEntity, p_fScale, p_fTime, p_bLoop, p_bInvertAtLoop, p_iLoopOccurs);

            // Ajout au moteur

            p_oEntity.Screen.Process2DStart(oProcess);

            // On retourne le process

            return (oProcess);
        }

        /// <summary>
        ///  Lance un effet tremblement sur l'objet
        /// </summary>
        /// <param name="p_oObject">Objet sur qui on fait le process</param>
        /// <param name="p_fAmplitude">Amplitude du tremblement en pixel</param>
        /// <param name="p_fInterval">Interval en milliseconde entre chaque mouvement</param>
        /// <param name="p_bOnX">TRUE tremblement sur l'axe X, FALSE sinon</param>
        /// <param name="p_bOnY">TRUE tremblement sur l'axe Y, FALSE sinon</param>
        /// <param name="p_fTime">Temps pour effectuer le tremblement en milliseconde</param>
        /// <param name="p_bLoop">TRUE redémare le process à la fin, FALSE sinon</param>
        /// <param name="p_iLoopOccurs">Indique combien de fois il doit boucler, NULL si boucle infinie</param>
        public static Process2DShake Shake(this Entity2D p_oEntity, float p_fAmplitude, float p_fInterval, bool p_bOnX, bool p_bOnY, float p_fTime, bool p_bLoop, int? p_iLoopOccurs)
        {
            // Vérification

            if ( p_oEntity == null )
                return (null);

            // Création du process

            Process2DShake oProcess = new Process2DShake(p_oEntity, p_fAmplitude, p_fInterval, p_bOnX, p_bOnY, p_fTime, p_bLoop, p_iLoopOccurs);

            // Ajout au moteur

            p_oEntity.Screen.Process2DStart(oProcess);

            // On retourne le process

            return (oProcess);
        }

        /// <summary>
        /// Lance un effet Translation sur l'objet
        /// </summary>
        /// <param name="p_oEntity">Objet sur qui on fait le process</param>
        /// <param name="p_fAngle">Coordonnée de déplacement (déplacement par rapport au point de départ)</param>
        /// <param name="p_fTime">Temps pour effectuer la translation en milliseconde</param>
        /// <param name="p_bLoop">TRUE redémare le process à la fin, FALSE sinon</param>
        /// <param name="p_bInvertAtLoop">TRUE si l'on inverse le type de l'effet, FALSE sinon</param>
        /// <param name="p_iLoopOccurs">Indique combien de fois il doit boucler, NULL si boucle infinie</param>
        /// <returns>Instance du process</returns>
        public static Process2DTranslation Translation(this Entity2D p_oEntity, Vector2 p_vMouvement, float p_fTime, bool p_bLoop, bool p_bInvertAtLoop, int? p_iLoopOccurs)
        {
            // Vérification

            if ( p_oEntity == null )
                return (null);

            // Création du process

            Process2DTranslation oProcess = new Process2DTranslation(p_oEntity, p_vMouvement, p_fTime, p_bLoop, p_bInvertAtLoop, p_iLoopOccurs);

            // Ajout au moteur

            p_oEntity.Screen.Process2DStart(oProcess);

            // On retourne le process

            return (oProcess);
        }
    }
}
